<template>
    <div>
        <!-- 面包屑导航区域 -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item>监控管理</el-breadcrumb-item>
            <el-breadcrumb-item :to="{ path: '/service' }">监控服务列表</el-breadcrumb-item>
            <el-breadcrumb-item>Grafana服务配置</el-breadcrumb-item>
        </el-breadcrumb>

        <!-- 内容主体区 -->
        <div :style="innerStyle">

            <!-- 内容明细区 -->
            <div style="position: relative; display: flex;">
                <el-card shadow="hover" style="width: 400px; height: 265px;">
                    <el-form ref="grafanaFormRef" :model="grafanaForm" label-width="90px">
                        <el-form-item label="服务地址">
                            <el-link type="primary">{{url}}</el-link>
                        </el-form-item>
                        <el-form-item label="SSH端口号">
                            <span style="color: brown;">{{grafanaForm.ssh_port}}</span>
                        </el-form-item>
                        <el-form-item label="普通用户名">
                            <span style="color: brown;">{{grafanaForm.user_normal}}</span>
                        </el-form-item>
                        <el-form-item label="HOME路径">
                            <span style="color: brown;">{{grafanaForm.home_path}}</span>
                        </el-form-item>
                    </el-form>
                </el-card>
                <el-card shadow="hover" style="flex: 1; margin-left: 5px;" :body-style="{ padding: '0px' }">
                    <el-table :data="grafanaForm.datasources" height="265" style="margin: 0px;" stripe>
                        <el-table-column prop="id" label="本地ID" width="65"></el-table-column>
                        <el-table-column prop="remote_id" label="远程ID" width="65"></el-table-column>
                        <el-table-column label="数据源类型" width="120">
                            <template slot-scope="scope">
                                <el-tag type="primary" size="mini" v-if="scope.row.datasource">prometheus</el-tag>
                                <el-tag type="warning" size="mini" v-else>无效</el-tag>
                            </template>
                        </el-table-column>
                        <el-table-column label="数据源地址">
                            <template slot-scope="scope">
                                <el-link type="primary" size="mini" v-if="scope.row.datasource" style="font-size: 12px;">
                                    http://{{scope.row.datasource.ipaddr}}:{{scope.row.datasource.service_port}}/
                                </el-link>
                                <el-tag type="warning" size="mini" v-else>无效</el-tag>
                            </template>
                        </el-table-column>
                        <el-table-column label="操作" width="80">
                            <template slot-scope="scope">
                                <el-popover
                                    placement="left"
                                    title="与 grafana.db 关联信息"
                                    width="400"
                                    trigger="click">

                                    <div style="padding: 0; margin: 0;">
                                        <p>url: {{scope.row.url}}</p>
                                        <p>uid: {{scope.row.uid}}</p>
                                    </div>
                                    <el-button size="mini" slot="reference" :disabled="scope.row.datasource == undefined || scope.row.uid == undefined">
                                        详情
                                    </el-button>
                                </el-popover>
                            </template>
                        </el-table-column>
                    </el-table>
                </el-card>

                <!-- 信息同步按钮 -->
                <div class="syncButtonGroup">
                    <el-popover
                        placement="left-start"
                        title="信息同步"
                        width="350"
                        trigger="hover"
                        content="以远程 grafana.db 数据文件中的 data_source 表信息为准，将数据源信息同步覆盖到本地（一般用于处理本地与远程信息不同步导致的差异化问题）。">
                        <el-button 
                            slot="reference" 
                            size="mini" 
                            type="success" 
                            icon="el-icon-sort-down" 
                            :disabled="grafanadbData.datasources.length == 0" 
                            @click="syncDataSources" round plain>同步数据源信息</el-button>
                    </el-popover>
                </div>
            </div>
            
            <!-- 内容配置区 -->
            <div style="height: calc(100% - 260px); margin-top: 5px;">
                <el-tabs v-model="fileName" style="height: 100%;" @tab-click="tabClick">
                    <el-tab-pane 
                        name="custom.ini" 
                        v-loading="loadingJobs[0].loading.enabled" 
                        :element-loading-text="loadingJobs[0].loading.text" 
                        element-loading-background="rgba(255, 255, 255, 1)">

                        <div class="tabButtonGroup">
                            <el-tooltip content="查找" placement="top-start">
                                <el-button size="mini" icon="el-icon-search" circle disabled></el-button>
                            </el-tooltip>
                            <el-tooltip content="编辑" placement="top-start">
                                <el-button size="mini" type="primary" icon="el-icon-edit" circle></el-button>
                            </el-tooltip>
                            <el-tooltip content="刷新" placement="top-start">
                                <el-button size="mini" type="success" icon="el-icon-refresh" circle disabled></el-button>
                            </el-tooltip>
                            <el-tooltip content="恢复" placement="top-start">
                                <el-button size="mini" type="danger" icon="el-icon-magic-stick" circle disabled></el-button>
                            </el-tooltip>
                            <el-tooltip content="收藏" placement="top-start">
                                <el-button size="mini" type="warning" icon="el-icon-star-off" circle disabled></el-button>
                            </el-tooltip>
                        </div>

                        <span slot="label"><i class="el-icon-document"></i> conf/custom.ini</span>
                        <div :style="`background: #F8F8F8; height: calc(${getInnerSize.height}px - 485px); overflow-y: scroll;`">
                            <highlightjs autodetect :code="loadingJobs[0].code" />
                        </div>
                    </el-tab-pane>
                    <el-tab-pane 
                        name="defaults.ini" 
                        v-loading="loadingJobs[1].loading.enabled" 
                        :element-loading-text="loadingJobs[1].loading.text" 
                        element-loading-background="rgba(255, 255, 255, 1)">

                        <span slot="label"><i class="el-icon-document"></i> conf/defaults.ini</span>
                        <div :style="`background: #F8F8F8; height: calc(${getInnerSize.height}px - 485px); overflow-y: scroll;`">
                            <highlightjs autodetect :code="loadingJobs[1].code" />
                        </div>
                    </el-tab-pane>
                    <el-tab-pane 
                        name="sample.ini" 
                        v-loading="loadingJobs[2].loading.enabled" 
                        :element-loading-text="loadingJobs[2].loading.text" 
                        element-loading-background="rgba(255, 255, 255, 1)">

                        <span slot="label"><i class="el-icon-document"></i> conf/sample.ini</span>
                        <div :style="`background: #F8F8F8; height: calc(${getInnerSize.height}px - 485px); overflow-y: scroll;`">
                            <highlightjs autodetect :code="loadingJobs[2].code" />
                        </div>
                    </el-tab-pane>
                    <el-tab-pane 
                        name="grafana.db"
                        v-loading="loadingJobs[3].loading.enabled" 
                        :element-loading-text="loadingJobs[3].loading.text" 
                        element-loading-background="rgba(255, 255, 255, 1)">

                        <span slot="label"><i class="el-icon-coin"></i> data/grafana.db</span>
                        <el-tabs v-model="grafanadbTab" type="border-card" tab-position="left" :style="`height: calc(${getInnerSize.height}px - 485px);`">
                            <el-tab-pane name="data_source">
                                <span slot="label"><i class="el-icon-receiving"></i> 数据源</span>
                                <el-table :data="grafanadbData.datasources" :height="getInnerSize.height - 485" style="width: 100%; margin: 0px;">
                                    <el-table-column prop="id" label="id" width="50"></el-table-column>
                                    <el-table-column prop="type" label="类型" width="150"></el-table-column>
                                    <el-table-column prop="name" label="名称" width="250"></el-table-column>
                                    <el-table-column prop="url" label="url"></el-table-column>
                                    <el-table-column prop="created" label="创建日期" width="180"></el-table-column>
                                    <el-table-column prop="uid" label="uid" width="180"></el-table-column>
                                </el-table>
                            </el-tab-pane>
                            <el-tab-pane name="dashboard">
                                <span slot="label"><i class="el-icon-data-line"></i> 仪表盘</span>
                                <el-table :data="grafanadbData.dashboards" :height="getInnerSize.height - 485" style="width: 100%; margin: 0px;">
                                    <el-table-column prop="id" label="id" width="50"></el-table-column>
                                    <el-table-column prop="title" label="标题" width="320"></el-table-column>
                                    <el-table-column label="内容">
                                        <template slot-scope="scope">
                                            {{scope.row.data.substring(0, 120)}}...
                                        </template>
                                    </el-table-column>
                                    <el-table-column prop="created" label="创建日期" width="150"></el-table-column>
                                    <el-table-column prop="uid" label="uid" width="250"></el-table-column>
                                </el-table>
                            </el-tab-pane>
                            <el-tab-pane name="alert">
                                <span slot="label"><i class="el-icon-bell"></i> 告警项</span>
                                <el-table :data="grafanadbData.alerts" :height="getInnerSize.height - 485" style="width: 100%; margin: 0px;">
                                    <el-table-column prop="id" label="id" width="50"></el-table-column>
                                    <el-table-column prop="dashboard_id" label="仪表盘id" width="80"></el-table-column>
                                    <el-table-column prop="name" label="告警名称" width="250"></el-table-column>
                                    <el-table-column prop="message" label="消息"></el-table-column>
                                    <el-table-column prop="created" label="创建日期" width="150"></el-table-column>
                                </el-table>
                            </el-tab-pane>
                        </el-tabs>

                    </el-tab-pane>
                </el-tabs>
            </div>
        </div>

    </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
    data: function () {
        return {
            serviceId: 0,
            grafanaForm: {},
            filePath: '',
            fileName: '',
            grafanadbTab: 'data_source',
            grafanadbData: {
                datasources: [],
                dashboards: [],
                alerts: [],
            },
            url: '',

            loadingJobs: [
                {
                    name: 'custom.ini',
                    path: 'conf',
                    loading: {
                        enabled: false,
                        text: ''
                    },
                    data: {},
                    code: ''
                },
                {
                    name: 'defaults.ini',
                    path: 'conf',
                    loading: {
                        enabled: false,
                        text: ''
                    },
                    data: {},
                    code: ''
                },
                {
                    name: 'sample.ini',
                    path: 'conf',
                    loading: {
                        enabled: false,
                        text: ''
                    },
                    data: {},
                    code: ''
                },
                {
                    name: 'grafana.db',
                    path: 'data',
                    loading: {
                        enabled: false,
                        text: ''
                    },
                    data: {},
                    code: ''
                }
            ]
        }
    },
    mounted: async function () {
        const command = this.$route.query.command;
        const fragments = command.split('@');
        this.serviceId = fragments[0];
        this.filePath = fragments[1];
        this.fileName = fragments[2];

        // 先行加载用户传入的文件信息
        await this.queryServiceInfo();
        if (this.grafanaForm) this.tabClick();
    },
    computed: {
        ...mapGetters(['getInnerSize']),
        innerStyle: function () {
            return `height: ${this.getInnerSize.height - 160}px;`;
        }
    },
    methods: {
        queryServiceInfo: async function () {
            const result = await this.$http.get(`grafana/${this.serviceId}`);
            const res = result.data;
            if (res.meta.status !== 201) return this.$message.error(`获取 Grafana 图形服务失败: ${res.meta.msg}`);

            this.grafanaForm = res.data;
            this.url = `http://${this.grafanaForm.ipaddr}:${this.grafanaForm.service_port}`;
            // console.log(this.grafanaForm);
        },
        tabClick: async function () {
            const job = this.loadingJobs.find(item => item.name === this.fileName);
            if (!job) return this.$message.error(`未知的配置文件名 ${this.fileName}`);
            if (job.data.jobid || job.loading.enabled) return;

            // 1.0 开启 UI 界面加载效果
            job.loading.enabled = true;
            job.loading.text = `正在获取配置文件 ${this.fileName} 的内容...`;

            // 2.0 请求下载配置文件
            const result = await this.$http.put(`grafana/fetch`, {
                pid: this.serviceId,
                file_path: job.path,
                file_name: job.name
            });
            const res = result.data;
            if (res.meta.status !== 201) {
                job.loading.text = `请求获取 ${job.path}/${job.name} 配置文件发生错误: ${res.meta.msg}`;
                return;
            }
            job.data.jobid = res.data.job_id;
            this.fetchJobData(job);
        },
        fetchJobData: function (job) {
            setTimeout(async () => {
                const result = await this.$http.get(`process/${job.data.jobid}`);
                const res = result.data;
                if (res.meta.status !== 201) {
                    job.loading.text = `获取配置文件 ${job.fileName} 的下载结果失败：${res.meta.msg}`;
                    return;
                }
                job.data = res.data;

                // 任务如果非错误和完成状态，则循环监听任务回执消息
                const statusCode = res.data.status;
                if (statusCode !== -1 && statusCode !== 2) this.fetchJobData(job);
                else this.fetchJobFileContent(job);
            }, 1000);
        },
        fetchJobFileContent: async function (job) {
            const msg = job.data.steps[0].message;
            const fragments = msg.split('\n');
            const localFilePath = fragments[fragments.length - 1];
            if (job.data.status !== 2) {
                job.loading.text = localFilePath;
                return;
            }
            // 读取下载到本地的文件
            if (localFilePath.endsWith(".db")) {
                // 创建读取 sqlite 文件任务
                const resultCreate = await this.$http.post(`file/sqlite`, {
                    local_file_path: localFilePath,
                    table_names: ['data_source', 'dashboard', 'alert']
                });
                const resCreate = resultCreate.data;
                if (resCreate.meta.status !== 201) {
                    job.loading.text = `读取配置文件 ${job.fileName} 的内容发生错误: ${resCreate.meta.msg}`;
                    return;
                }
                // 获取读取的 sqlite 文件结果
                const resultFetch = await this.$http.get(`file/sqlite`, {
                    params: {
                        tid: resCreate.data.tid
                    }
                });
                const resFetch = resultFetch.data;
                if (resFetch.meta.status !== 200) {
                    job.loading.text = `读取配置文件 ${job.fileName} 的内容发生错误: ${resFetch.meta.msg}`;
                    return;
                }
                const sqliteData = resFetch.data.file_content;
                const sqliteObjectDatas = sqliteData.find(data => data.table_name === 'data_source');
                const sqliteObjectDashb = sqliteData.find(data => data.table_name === 'dashboard');
                const sqliteObjectAlert = sqliteData.find(data => data.table_name === 'alert');
                
                this.grafanadbData.datasources = sqliteObjectDatas.rows;
                this.grafanadbData.dashboards = sqliteObjectDashb.rows;
                this.grafanadbData.alerts = sqliteObjectAlert.rows;

            } else {
                // 读取普通文本文件
                const result = await this.$http.get(`file/txt`, {
                    params: {
                        local_file_path: localFilePath
                    }
                });
                const res = result.data;
                if (res.meta.status !== 200) {
                    job.loading.text = `读取配置文件 ${job.fileName} 的内容发生错误: ${res.meta.msg}`;
                    return;
                }
                job.code = res.data.file_content;
            }
            job.loading.enabled = false;
        },
        syncDataSources: async function () {
            const result = await this.$http.put(`grafana/datasource/sync`, {
                id: this.serviceId,
                datasourceRows: this.grafanadbData.datasources
            });
            const res = result.data;
            if (res.meta.status !== 201) return this.$message.error(`同步数据源信息失败: ${res.meta.msg}`);

            console.log("result: ", res);
            this.$message.success(`同步数据源信息完成`);
            this.queryServiceInfo();
        }
    }
}
</script>

<style lang="less" scoped>
    .syncButtonGroup {
        position: absolute;
        right: 30px;
        bottom: 15px;
    }

    .el-tab-pane {
        overflow: hidden;
        position: relative;
    }

    .tabButtonGroup {
        position: absolute;
        right: 30px;
        top: 15px;
    }
</style>
